package com.htstar.ovms.device.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.htstar.ovms.admin.api.feign.EtpInfoFeign;
import com.htstar.ovms.admin.api.vo.EtpInfoSVo;
import com.htstar.ovms.common.core.constant.CommonConstants;
import com.htstar.ovms.common.core.util.OvmDateUtil;
import com.htstar.ovms.common.security.service.OvmsUser;
import com.htstar.ovms.common.security.util.SecurityUtils;
import com.htstar.ovms.device.api.dto.*;
import com.htstar.ovms.device.api.entity.CarViolations;
import com.htstar.ovms.device.api.vo.CarViolationsVO;
import com.htstar.ovms.device.api.vo.DeviceTripCountTotalVO;
import com.htstar.ovms.device.api.vo.DeviceTripVO;
import com.htstar.ovms.device.mapper.CarViolationsMapper;
import com.htstar.ovms.device.service.CarViolationsService;
import com.htstar.ovms.device.service.DeviceTripService;
import com.htstar.ovms.device.service.GpsService;
import com.htstar.ovms.device.util.Cp;
import com.htstar.ovms.device.util.GpsNewUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

/**
 * @author htxk
 * @date 2020-10-29 18:39:11
 */
@Service
public class CarViolationsServiceImpl extends ServiceImpl<CarViolationsMapper, CarViolations> implements CarViolationsService {
    @Autowired
    DeviceTripService deviceTripService;
    @Autowired
    EtpInfoFeign etpInfoFeign;
    @Autowired
    private GpsService gpsService;

    /**
     * 违规车辆查询企业和下级企业旧版
     * 金柱
     *
     * @param carViolationsDTO
     * @return
     */
    @Override
    public Page<CarViolationsVO> getAllCarViolationsPage(CarViolationsDTO carViolationsDTO) {
        String endStar= null;
        if (Objects.equals(carViolationsDTO.getEtpId(), null)) {
            carViolationsDTO.setEtpId(SecurityUtils.getUser().getEtpId());
        }
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(carViolationsDTO.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            carViolationsDTO.setEtpIds(etpInfoSVo.getIds());
        });
        DeviceTripListDTO cp2 = Cp.cp(carViolationsDTO, new DeviceTripListDTO());
        CarViolationsListDTO cp1 = Cp.cp(carViolationsDTO, new CarViolationsListDTO());
        List<CarViolationsVO> list = new ArrayList<>();
        List<CarViolations> listUpdate = new ArrayList<>();
        List<CarViolationsVO> records = baseMapper.getAllCarViolationsPage(carViolationsDTO).getRecords();
        for (CarViolationsVO carViolationsVO : records) {
            endStar=carViolationsVO.getEndAddr();
            cp2.setStartTime(carViolationsVO.getStaTime());
            cp2.setEndTime(carViolationsVO.getEndTime());
            if( StrUtil.isBlank(carViolationsVO.getEndAddr()) && StrUtil.isBlank(carViolationsVO.getEndLatlon())) {
                DeviceTripCountTotalVO tripInfoByDeviceSnPage = deviceTripService.getTripInfoByDeviceSns(cp2);
                if (tripInfoByDeviceSnPage != null) {
                    if (tripInfoByDeviceSnPage.getDeviceTrips() != null) {
                        for (DeviceTripVO deviceTripVO : tripInfoByDeviceSnPage.getDeviceTrips()) {
                            carViolationsVO.setStaAddr(deviceTripVO.getStaAddr());
                            carViolationsVO.setEndAddr(deviceTripVO.getEndAddr());
                            carViolationsVO.setStaLatlon(deviceTripVO.getStaLatlon());
                            carViolationsVO.setEndLatlon(deviceTripVO.getEndLatlon());
                        }
                    }
                }
            }

            if (StrUtil.isNotBlank(carViolationsVO.getEndLatlon())) {
                //WGS84坐标转换GCJ-02坐标  （国内通用是WGS84 高德是GCJ-02）
                if (!Objects.equals(null, carViolationsVO.getStaLatlon())) {
                    String[] split = StrUtil.split(carViolationsVO.getStaLatlon(), ",");
                    Double lat = Double.valueOf(Double.parseDouble(split[0]));
                    Double lng = Double.valueOf(Double.parseDouble(split[1]));
                    double[] doubles = GpsNewUtil.toGCJ02Point(lat, lng, 5);
                    carViolationsVO.setStaLatlon(doubles[0] + "," + doubles[1]);
                }
                String[] split = StrUtil.split(carViolationsVO.getEndLatlon(), ",");
                Double lat = Double.valueOf(Double.parseDouble(split[0]));
                Double lng = Double.valueOf(Double.parseDouble(split[1]));
                double[] doubles = GpsNewUtil.toGCJ02Point(lat, lng, 5);
                carViolationsVO.setEndLatlon(doubles[0] + "," + doubles[1]);
                if (StrUtil.isBlank(carViolationsVO.getEndAddr()) || Objects.equals("",carViolationsVO.getEndAddr())) {
                    String endAddr = gpsService.getGpsAddr(doubles[0], doubles[1]);
                    carViolationsVO.setEndAddr(endAddr);
                }
            }
            CarViolations cp = Cp.cp(carViolationsVO, new CarViolations());
               /*判断查询的结束位置和地址是否为空，不为空判断解析的地址是否为空，不为空则更新地址到数据库，避免每次都要调用gps解析*/
            if(StrUtil.isBlank(endStar)){
                if(StrUtil.isNotBlank(cp.getEndAddr()) && StrUtil.isNotBlank(cp.getEndLatlon())){
                    listUpdate.add(cp);
                }
            }
            list.add(carViolationsVO);
        }
        if(!listUpdate.isEmpty()){
            this.updateBatchById(listUpdate);
        }
        Page<CarViolationsVO> pages = new Page<>();
        pages.setRecords(list);
        pages.setTotal(baseMapper.getAllCarViolationsCount(cp1));
        return pages;
    }

    /**
     * 违规车辆查询企业和下级企业 新改动
     * jinzhu
     *
     * @param carViolationsDTO
     * @return
     */
    //@Override
    public Page<CarViolationsVO> getAllCarViolationsPages(CarViolationsDTO carViolationsDTO) {
        if (Objects.equals(carViolationsDTO.getEtpId(), null)) {
            carViolationsDTO.setEtpId(SecurityUtils.getUser().getEtpId());
        }
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(carViolationsDTO.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            carViolationsDTO.setEtpIds(etpInfoSVo.getIds());
        });
        LocalDateTime now = OvmDateUtil.getCstNow();
        CarViolationsListDTO cp1 = Cp.cp(carViolationsDTO, new CarViolationsListDTO());
        List<CarViolationsVO> list = new ArrayList<>();
        List<CarViolationsVO> records = baseMapper.getAllCarViolationsPage(carViolationsDTO).getRecords();
        for (CarViolationsVO carViolationsVO : records) {
            //WGS84坐标转换GCJ-02坐标  （国内通用是WGS84 高德是GCJ-02）
            if (!Objects.equals(null, carViolationsVO.getStaLatlon())) {
                String[] split = StrUtil.split(carViolationsVO.getStaLatlon(), ",");
                Double lat = Double.valueOf(Double.parseDouble(split[0]));
                Double lng = Double.valueOf(Double.parseDouble(split[1]));
                double[] doubles = GpsNewUtil.toGCJ02Point(lat, lng, 5);
                carViolationsVO.setStaLatlon(doubles[0] + "," + doubles[1]);
            }
            if (!Objects.equals(null, carViolationsVO.getEndLatlon())) {
                String[] split = StrUtil.split(carViolationsVO.getEndLatlon(), ",");
                Double lat = Double.valueOf(Double.parseDouble(split[0]));
                Double lng = Double.valueOf(Double.parseDouble(split[1]));
                double[] doubles = GpsNewUtil.toGCJ02Point(lat, lng, 5);
                carViolationsVO.setEndLatlon(doubles[0] + "," + doubles[1]);
                if (StrUtil.isNotBlank(carViolationsVO.getEndAddr())) {
                    //日期时间转换时间戳
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    long sta = LocalDateTime.parse(carViolationsVO.getStaTime(), formatter).toEpochSecond(ZoneOffset.of("+8"));
                    long end = now.toEpochSecond(ZoneOffset.of("+8"));
                    //判断时间戳是否大于120  和 小于 300 秒
                    long l = end - sta;
                    if (StrUtil.isNotBlank(carViolationsVO.getEndAddr()) && (l > 120 && l < 300)) {
                        String endAddr = gpsService.getGpsAddr(doubles[0], doubles[1]);
                        carViolationsVO.setEndAddr(endAddr);
                    }
                } else {
                    String endAddr = gpsService.getGpsAddr(doubles[0], doubles[1]);
                    carViolationsVO.setEndAddr(endAddr);
                }
            }
            list.add(carViolationsVO);
        }
        Page<CarViolationsVO> pages = new Page<>();
        pages.setRecords(list);
        pages.setTotal(baseMapper.getAllCarViolationsCount(cp1));
        return pages;
    }


    /**
     * 违规车辆查询企业和下级企业导出
     *
     * @param carViolationsDTO
     * @return
     */
    @Override
    public List<CarViolationsVO> exportCarViolationsVO(CarViolationsDTO carViolationsDTO) {
        String endStar= null;
        CarViolationsListDTO cp1 = Cp.cp(carViolationsDTO, new CarViolationsListDTO());
        if (!Objects.equals(carViolationsDTO.getId(), null) && !Objects.equals(carViolationsDTO.getId(), "")) {
            int[] objects = Arrays.stream(carViolationsDTO.getId().split(","))
                    .mapToInt(s -> Integer.parseInt(s)).toArray();
            cp1.setId(objects);
        }
        DeviceTripListDTO cp2 = Cp.cp(cp1, new DeviceTripListDTO());
        List<CarViolationsVO> list = new ArrayList<>();
        List<CarViolations> listUpdate = new ArrayList<>();
        CarViolations carViolations = null;
        List<CarViolationsVO> allCarViolations = baseMapper.getAllCarViolations(cp1);
        for (CarViolationsVO allCarViolation : allCarViolations) {
            endStar=allCarViolation.getEndAddr();
            if( StrUtil.isBlank(allCarViolation.getEndAddr()) && StrUtil.isBlank(allCarViolation.getEndLatlon())) {
                cp2.setLicCode(allCarViolation.getLicCode());
                cp2.setStartTime(allCarViolation.getStaTime());
                cp2.setEndTime(allCarViolation.getEndTime());
                DeviceTripCountTotalVO tripInfoByDeviceSnPage = deviceTripService.getTripInfoByDeviceSns(cp2);
                if (tripInfoByDeviceSnPage != null) {
                    if (tripInfoByDeviceSnPage.getDeviceTrips() != null) {
                        for (DeviceTripVO deviceTripVO : tripInfoByDeviceSnPage.getDeviceTrips()) {
                            allCarViolation.setStaAddr(deviceTripVO.getStaAddr());
                            allCarViolation.setEndAddr(deviceTripVO.getEndAddr());
                            allCarViolation.setStaLatlon(deviceTripVO.getStaLatlon());
                            allCarViolation.setEndLatlon(deviceTripVO.getEndLatlon());
                        }
                    }
                }
            }
      /*      WGS84坐标转换GCJ-02坐标  （国内通用是WGS84 高德是GCJ-02）*/

            if (StrUtil.isNotBlank(allCarViolation.getEndLatlon())) {
                if (!Objects.equals(null, allCarViolation.getStaLatlon())) {
                    String[] split = StrUtil.split(allCarViolation.getStaLatlon(), ",");
                    Double lat = Double.valueOf(Double.parseDouble(split[0]));
                    Double lng = Double.valueOf(Double.parseDouble(split[1]));
                    double[] doubles = GpsNewUtil.toGCJ02Point(lat, lng, 5);
                    allCarViolation.setStaLatlon(doubles[0] + "," + doubles[1]);
                }
                String[] split = StrUtil.split(allCarViolation.getEndLatlon(), ",");
                Double lat = Double.valueOf(Double.parseDouble(split[0]));
                Double lng = Double.valueOf(Double.parseDouble(split[1]));
                double[] doubles = GpsNewUtil.toGCJ02Point(lat, lng, 5);
                allCarViolation.setEndLatlon(doubles[0] + "," + doubles[1]);
                if (StrUtil.isBlank(allCarViolation.getEndAddr())) {
                    String endAddr = gpsService.getGpsAddr(doubles[0], doubles[1]);
                    allCarViolation.setEndAddr(endAddr);
                }
            }
            carViolations=new CarViolations();
            CarViolations cp = Cp.cp(allCarViolation, carViolations);
            /*判断查询的结束位置和地址是否为空，不为空判断解析的地址是否为空，不为空则更新地址到数据库，避免每次都要调用gps解析*/
            if(StrUtil.isBlank(endStar)){
                if(StrUtil.isNotBlank(cp.getEndAddr()) && StrUtil.isNotBlank(cp.getEndLatlon())){
                    listUpdate.add(cp);
                }
            }
            list.add(allCarViolation);
        }
        if(!listUpdate.isEmpty()){
            this.updateBatchById(listUpdate);
        }
//        // 消息汇总
//        ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
//        ListenableFuture futrue = service.submit(new Callable() {
//            @Override
//            public List<CarViolationsVO> call() {
//                return list;
//            }
//        });
        return list;
    }


    //获取企业
    public DeviceTripDTO getEdpId(CarViolationsDTO carViolationsDTO) {
        OvmsUser user = SecurityUtils.getUser();
        DeviceTripDTO cp = Cp.cp(carViolationsDTO, new DeviceTripDTO());
        if (carViolationsDTO.getEtpId() == null && user != null) {//pc端企业判断
            if (user.getEtpId() != CommonConstants.ETP_ID_1) {
                carViolationsDTO.setEtpId(user.getEtpId());
            } else {
                carViolationsDTO.setEtpId(null);
            }
        }
        return cp;
    }

    @Override
    public Page<CarViolationsVO> getCarViolationsPageForMultiEtpId(CarViolationsDTO carViolationsDTO) {
        DeviceTripDTO cp = this.getEdpId(carViolationsDTO);
        OvmsUser user = SecurityUtils.getUser();
        DeviceTripListDTO cp2 = Cp.cp(cp, new DeviceTripListDTO());
        List<CarViolationsVO> list = new ArrayList<>();
        if (carViolationsDTO.getEtpIds() == null) {
            ArrayList<Integer> etpIdsList = new ArrayList<>();
            etpIdsList.add(user.getEtpId());
            carViolationsDTO.setEtpIds(etpIdsList);
        }
        CarViolationsListDTO cp1 = Cp.cp(carViolationsDTO, new CarViolationsListDTO());//用于查询pageTotal信息
        Page<CarViolationsVO> rs = baseMapper.getCarViolationsPageForMultiEtpId(carViolationsDTO);
        for (CarViolationsVO carViolationsVO : rs.getRecords()) {
            cp.setEtpId(carViolationsVO.getEtpId());
            cp.setLicCode(carViolationsVO.getLicCode());
            cp.setStartTime(carViolationsVO.getStaTime());
            cp.setEndTime(carViolationsVO.getEndTime());
            DeviceTripTotalDTO deviceTripTotalDTO = new DeviceTripTotalDTO();
            BeanUtils.copyProperties(cp, deviceTripTotalDTO);
            cp2.setLicCode(carViolationsVO.getLicCode());
            cp2.setEtpId(carViolationsVO.getEtpId());
            cp2.setEtpIds(carViolationsDTO.getEtpIds());
            DeviceTripCountTotalVO tripInfoByDeviceSnPage = deviceTripService.getTripInfoByDeviceSn(cp2);
            if (tripInfoByDeviceSnPage != null) {
                if (tripInfoByDeviceSnPage.getDeviceTrips() != null) {
                    for (DeviceTripVO deviceTripVO : tripInfoByDeviceSnPage.getDeviceTrips()) {
                        carViolationsVO.setStaAddr(deviceTripVO.getStaAddr());
                        carViolationsVO.setEndAddr(deviceTripVO.getEndAddr());
                        carViolationsVO.setStaLatlon(deviceTripVO.getStaLatlon());
                        carViolationsVO.setEndLatlon(deviceTripVO.getEndLatlon());
                    }
                }
            } else {
                carViolationsVO.setStaAddr(null);
                carViolationsVO.setEndAddr(null);
                carViolationsVO.setStaLatlon(null);
                carViolationsVO.setEndLatlon(null);
            }
            list.add(carViolationsVO);
        }

        Page<CarViolationsVO> pages = new Page<>();
        pages.setRecords(list);
        pages.setTotal(baseMapper.getAllCarViolationsCountForMultiEtp(cp1));
        return pages;
    }
}
